﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//
using System.ComponentModel;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Globalization;

namespace Editor
{
    /// <summary>
    /// EditableVector3Converter
    /// </summary>
    class EditableVector3Converter : ExpandableObjectConverter
    {
        EditableVector3 mValue = null;

        public override bool CanConvertFrom(ITypeDescriptorContext context,
            Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }

        // Overrides the ConvertFrom method of TypeConverter.
        public override object ConvertFrom(ITypeDescriptorContext context,
           CultureInfo culture, object value)
        {
            if (value is string && mValue != null)
            {
                mValue.FromString(value as string);
                return mValue;
            }
            return base.ConvertFrom(context, culture, value);
        }
        // Overrides the ConvertTo method of TypeConverter.
        public override object ConvertTo(ITypeDescriptorContext context,
           CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                mValue = (value as EditableVector3);
                return mValue.ToString();
            }
            else
            {
                mValue = null;
                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }

    /// <summary>
    /// EditableQuaternionConverter
    /// </summary>
    class EditableQuaternionConverter : ExpandableObjectConverter
    {
        EditableQuaternion mValue = null;

        public override bool CanConvertFrom(ITypeDescriptorContext context,
            Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }

        // Overrides the ConvertFrom method of TypeConverter.
        public override object ConvertFrom(ITypeDescriptorContext context,
           CultureInfo culture, object value)
        {
            if (value is string && mValue != null)
            {
                mValue.FromString(value as string);
                return mValue;
            }
            return base.ConvertFrom(context, culture, value);
        }
        // Overrides the ConvertTo method of TypeConverter.
        public override object ConvertTo(ITypeDescriptorContext context,
           CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                mValue = (value as EditableQuaternion);
                return mValue.ToString();
            }
            else
            {
                mValue = null;
                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }

    /// <summary>
    /// EditorObject
    /// </summary>
    public class EditorObject
    {
        //
    }

    /// <summary>
    /// EditableVector3
    /// </summary>
    public class EditableVector3
    {
        private const char ValueSepartor = ';';

        public delegate IDK.Vector3 Getter(); 
        public delegate void Setter(IDK.Vector3 vec); 

        private Getter Get;
        private Setter Set;

        public EditableVector3(Getter getter, Setter setter)
        {
            Get = getter;
            Set = setter;
        }

		public override String ToString()
		{
            return String.Format("{1}{0} {2}{0} {3}", ValueSepartor, x, y, z);
		}

        public void FromString(String str)
        {
            string[] strArray = str.Split(new char[] { ValueSepartor });

            Set(new IDK.Vector3(
                float.Parse(strArray[0]),
                float.Parse(strArray[1]),
                float.Parse(strArray[2])));
        }

        /// <summary>
        /// HARDCODE
        /// </summary>
        public float this[int i]
        {
            get
            {
                IDK.Vector3 temp = Get();
                switch (i)
                {
                    case 0:
                        return temp.x;
                    case 1:
                        return temp.y;
                    case 2:
                        return temp.z;
                }
                throw new Exception();
            }

            set
            {
                IDK.Vector3 temp = Get();
                switch (i)
                {
                    case 0:
                        temp.x = value;
                        break;
                    case 1:
                        temp.y = value;
                        break;
                    case 2:
                        temp.z = value;
                        break;
                }
                Set(temp);
            }
        }

        public float x
        {
            get { return this[0]; }
            set { this[0] = value; }
        }

        public float y
        {
            get { return this[1]; }
            set { this[1] = value; }
        }

        public float z
        {
            get { return this[2]; }
            set { this[2] = value; }
        }
    }

    /// <summary>
    /// EditableQuaternion
    /// </summary>
    public class EditableQuaternion
    {
        private const char ValueSepartor = ';';

        public delegate IDK.Quaternion Getter();
        public delegate void Setter(IDK.Quaternion vec);

        private Getter Get;
        private Setter Set;

        public EditableQuaternion(Getter getter, Setter setter)
        {
            Get = getter;
            Set = setter;
        }

        public override String ToString()
        {
            return String.Format("{1}{0} {2}{0} {3}{0} {4}", ValueSepartor, x, y, z, w);
        }

        public void FromString(String str)
        {
            string[] strArray = str.Split(new char[] { ValueSepartor });
            //NOTE: Quat intialization w,x,y,z
            Set(new IDK.Quaternion(
                float.Parse(strArray[3]), 
                float.Parse(strArray[0]),
                float.Parse(strArray[1]),
                float.Parse(strArray[2])));
        }

        /// <summary>
        /// HARDCODE
        /// </summary>
        public float this[int i]
        {
            get
            {
                IDK.Quaternion temp = Get();
                switch (i)
                {
                    case 0:
                        return temp.x;
                    case 1:
                        return temp.y;
                    case 2:
                        return temp.z;
                    case 3:
                        return temp.w;
                }
                throw new Exception();
            }

            set
            {
                IDK.Quaternion temp = Get();
                switch (i)
                {
                    case 0:
                        temp.x = value;
                        break;
                    case 1:
                        temp.y = value;
                        break;
                    case 2:
                        temp.z = value;
                        break;
                    case 3:
                        temp.w = value;
                        break;
                }
                Set(temp);
            }
        }


        public float x
        {
            get { return this[0]; }
            set { this[0] = value; }
        }

        public float y
        {
            get { return this[1]; }
            set { this[1] = value; }
        }

        public float z
        {
            get { return this[2]; }
            set { this[2] = value; }
        }

        public float w
        {
            get { return this[3]; }
            set { this[3] = value; }
        }
    }

    public class EditableGameInfo
    {
        Game.GameObjectInfo mSource;
        public EditableGameInfo(Game.GameObjectInfo source)
        {
            mSource = source;
        }

        
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public Game.GameObjectInfo Source
        {
            get
            {
                return mSource;
            }
        }
    }

    class EditableGameInfoConverter : ExpandableObjectConverter
    {
        EditableGameInfo mSource;

        public EditableGameInfoConverter(EditableGameInfo source)
        {
            mSource = source;
        }
    }

    public class EditorSceneObject : EditorObject
    {
        public IDK.SceneNode SceneNode;

        EditableVector3 mEditablePostion;
        EditableQuaternion mEditableRotation;
        EditableGameInfo mEditableGameInfo;

        public EditorSceneObject(IDK.SceneNode sceneNode)
        {
            SceneNode = sceneNode;
            mEditablePostion = new EditableVector3(sceneNode.GetTransformation().GetLocalPosition, sceneNode.GetTransformation().SetLocalPosition);
            mEditableRotation = new EditableQuaternion(sceneNode.GetTransformation().GetLocalOrientation, sceneNode.GetTransformation().SetLocalOrientation);
        }

        public String Name
        {
            get { return SceneNode.GetName(); }
        }

        [TypeConverter(typeof(EditableVector3Converter))]
        public EditableVector3 Position
        {
            get { return mEditablePostion; }
            set { mEditablePostion = value; }
        }

        [TypeConverter(typeof(EditableQuaternionConverter))]
        public EditableQuaternion Rotation
        {
            get { return mEditableRotation; }
            set { mEditableRotation = value; }
        }


        [TypeConverter(typeof(ExpandableObjectConverter))]
        public EditableGameInfo GameObjectInfo
        {
            get { return mEditableGameInfo; }
            set { mEditableGameInfo = value; }
        }
    }

    class GroupEditorSceneObject : List<EditorSceneObject>
    {
       
    }

    class EditorScene : Game.GameScene
    {
        public EditorScene(IDK.Engine engine)
            : base(engine)
        {
            Pause = true;
        }

        public void SwitchGameMode(bool mode)
        {
            ActionManager.InputSubscriber.Enable(mode);
        }
    }
}
